package com.xmg.boot.demo.bootlesson1.user.aspect;

import com.xmg.boot.demo.bootlesson1.user.annotation.MyLog;
import com.xmg.boot.demo.bootlesson1.user.controller.UserController;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ma
 * @date 2023/11/15
 * @description 切面实现类
 */

//声明组件
@Component
//声明切面Bean
@Aspect
public class MyLogAspect {
    //设置日志文件
    private final Logger logger= LoggerFactory.getLogger(MyLogAspect.class);
    /**
     * 配置切入点，其他芳芳共同此配置点
     * - * com.wmx.aspect.EmpService.*(..))：表示 com.wmx.aspect.EmpService 类中的任意方法
     * - * com.wmx.aspect.*.*(..))：表示 com.wmx.aspect 包(不含子包)下任意类中的任意方法
     * - * com.wmx.aspect..*.*(..))：表示 com.wmx.aspect 包及其子包下任意类中的任意方法  , 这个不能乱用，容易出错啊
     */
    @Pointcut("execution(* com.xmg.boot.demo.bootlesson1.user.controller.*.*(..))")
    public void aspect(){}

    @Before("aspect()")
    public void Before(){
        System.out.println("----------before开始执行");
    }

    @After("aspect()")
    public void After(){
        System.out.println("----------after开始执行");
    }

    @AfterThrowing(pointcut="aspect()",throwing="e")
    public void AfterThrowing(Throwable e){
        System.out.println("----------aferThrowing开始执行"+e);
    }

    @Around("aspect()")
    public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取自定义注解里面的值
        Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
        MyLog logAnnotation = method.getAnnotation(MyLog.class);

        if(logAnnotation==null){
            return joinPoint.proceed();
        }

        System.out.println("operateType:------"+logAnnotation.type());
        System.out.println("operateExplain:------"+logAnnotation.explain());
        //获取入参
        Object[] objs = joinPoint.getArgs();
        String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); // 参数名
        if(objs.length<=0){
            return joinPoint.proceed();
        }
        Map<String, Object> paramMap = new HashMap<String, Object>();
        for (int i = 0; i < objs.length; i++) {
            paramMap.put(argNames[i], objs[i]);
        }
        System.out.println("入参:"+paramMap.toString());
        logger.info(logAnnotation.type()+ "  入参:"+paramMap.toString());
        //获取出参
        Object result =joinPoint.proceed();
        System.out.println("出参:"+result.toString());
        logger.info(logAnnotation.type()+ "  出参:"+result.toString());
        return result;
    }

    @AfterReturning("aspect()")
    public void AfterReturning(){
        System.out.println("--------AfterReturning方法开始执行");
    }


}
